# Cargar librerías
library(ahp)
library(knitr)
library(kableExtra)Trabajo 2 sobre Decisión Multicriterio
1. Introducción del problema
El trabajo trata sobre el problema de decisión multicriterio de “Seleccionar el mejor piso de alquiler para un estudiante”. El objetivo es evaluar 4 alternativas de pisos basándose en una jerarquía de 4 criterios principales (Económico, Ubicación, Calidad y Ambiente) y sus 10 subcriterios correspondientes.
Alternativas (Pisos):
- A_Cercano: Al lado de la facultad, pero caro y antiguo.
- B_Reformado: Algo alejado, pero moderno, de alta calidad y precio medio.
- C_Barato: Muy lejos y de baja calidad, pero extremadamente barato.
- D_Centrico: En el centro, ideal para ocio, pero ruidoso y lejos de la facultad.
Jerarquía de Criterios:
- 1. Económico: (C1.1: Alquiler, C1.2: Gastos, C1.3: Transporte)
- 2. Ubicación: (C2.1: Tiempo Uni, C2.2: Conexión, C2.3: Servicios)
- 3. Calidad: (C3.1: Estado, C3.2: Tamaño Hab.)
- 4. Ambiente: (C4.1: Ruido, C4.2: N.º Compis)
Para ello, se aplicarán las técnicas, comenzando por el Proceso Analítico Jerárquico (AHP), seguido de ELECTRE y PROMETHEE. Finalmente, se compararán los resultados y se extraerán conclusiones.
2. Proceso Analítico Jerárquico (AHP)
Para el método AHP, se utiliza el paquete ahp de R. Este método requiere la definición de la jerarquía y la comparación por pares de todos los elementos en cada nivel, lo cual se ha definido en el fichero pisos.ahp.
2.1 Cálculo del Modelo AHP (con librería)
# Cargar y Calcular AHP
# 1. Cargar el modelo desde el fichero
model <- ahp::Load("pisos.ahp")
# 2. Calcular las prioridades
ahp::Calculate(model)
# 3. Analizar los resultados
results_table <- as.data.frame(ahp::AnalyzeTable(model))
results_priority <- as.data.frame(ahp::AnalyzeTable(model, variable = "priority", sort = "orig"))
rownames(results_table) <- results_table[, 1]
rownames(results_priority) <- results_priority[, 1]2.2 Diagrama de jerarquía
# Mostrar Diagrama
Visualize(model)2.3 Resultados y Análisis AHP
Las tablas generadas por el paquete ahp nos permiten analizar el ranking final, los pesos de cada criterio y, fundamentalmente, la consistencia de nuestros juicios.
# Mostrar Tablas de Resultados
# 1. Tabla de Análisis (Resultados Finales AHP)
kbl(results_table, digits = 4, caption = "Resultados Finales AHP: Contribución Total") %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "center")| Weight | C_Barato | A_Cercano | D_Centrico | B_Reformado | Inconsistency | ||
|---|---|---|---|---|---|---|---|
| Mejor Piso de Alquiler | Mejor Piso de Alquiler | 1.0000 | 0.3482 | 0.2618 | 0.2062 | 0.1838 | 0.0442 |
| Económico | Económico | 0.5650 | 0.2589 | 0.1248 | 0.1239 | 0.0574 | 0.0367 |
| Alquiler | Alquiler | 0.3599 | 0.2366 | 0.0165 | 0.0730 | 0.0339 | 0.0645 |
| Transporte | Transporte | 0.1459 | 0.0075 | 0.1027 | 0.0178 | 0.0178 | 0.0344 |
| Gastos | Gastos | 0.0592 | 0.0148 | 0.0056 | 0.0331 | 0.0056 | 0.0164 |
| Ubicación | Ubicación | 0.2622 | 0.0391 | 0.1234 | 0.0394 | 0.0603 | 0.0367 |
| Tiempo Uni | Tiempo Uni | 0.1670 | 0.0072 | 0.1167 | 0.0141 | 0.0291 | 0.0991 |
| Conexión | Conexión | 0.0677 | 0.0304 | 0.0035 | 0.0098 | 0.0241 | 0.0776 |
| Servicios | Servicios | 0.0275 | 0.0015 | 0.0032 | 0.0155 | 0.0072 | 0.0442 |
| Calidad | Calidad | 0.1175 | 0.0373 | 0.0101 | 0.0168 | 0.0533 | 0.0000 |
| Estado | Estado | 0.0588 | 0.0045 | 0.0045 | 0.0112 | 0.0386 | 0.0278 |
| Tamaño Hab. | Tamaño Hab. | 0.0588 | 0.0329 | 0.0056 | 0.0056 | 0.0147 | 0.0164 |
| Ambiente | Ambiente | 0.0553 | 0.0129 | 0.0035 | 0.0260 | 0.0129 | 0.0000 |
| Ruido | Ruido | 0.0415 | 0.0087 | 0.0022 | 0.0219 | 0.0087 | 0.0278 |
| N.º Compis | N.º Compis | 0.0138 | 0.0041 | 0.0014 | 0.0041 | 0.0041 | 0.0000 |
# 2. Tabla de Prioridades (Alternativas por Criterio)
kbl(results_priority, digits = 4, caption = "Prioridades Locales por Subcriterio") %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "center")| Priority | A_Cercano | B_Reformado | C_Barato | D_Centrico | Inconsistency | ||
|---|---|---|---|---|---|---|---|
| Mejor Piso de Alquiler | Mejor Piso de Alquiler | 1.0000 | NA | NA | NA | NA | 0.0442 |
| Económico | Económico | 0.5650 | NA | NA | NA | NA | 0.0367 |
| Alquiler | Alquiler | 0.6370 | 0.0457 | 0.0942 | 0.6574 | 0.2027 | 0.0645 |
| Gastos | Gastos | 0.1047 | 0.0955 | 0.0955 | 0.2495 | 0.5596 | 0.0164 |
| Transporte | Transporte | 0.2583 | 0.7039 | 0.1222 | 0.0517 | 0.1222 | 0.0344 |
| Ubicación | Ubicación | 0.2622 | NA | NA | NA | NA | 0.0367 |
| Tiempo Uni | Tiempo Uni | 0.6370 | 0.6987 | 0.1740 | 0.0431 | 0.0842 | 0.0991 |
| Conexión | Conexión | 0.2583 | 0.0512 | 0.3554 | 0.4486 | 0.1448 | 0.0776 |
| Servicios | Servicios | 0.1047 | 0.1175 | 0.2622 | 0.0553 | 0.5650 | 0.0442 |
| Calidad | Calidad | 0.1175 | NA | NA | NA | NA | 0.0000 |
| Estado | Estado | 0.5000 | 0.0760 | 0.6570 | 0.0760 | 0.1911 | 0.0278 |
| Tamaño Hab. | Tamaño Hab. | 0.5000 | 0.0955 | 0.2495 | 0.5596 | 0.0955 | 0.0164 |
| Ambiente | Ambiente | 0.0553 | NA | NA | NA | NA | 0.0000 |
| Ruido | Ruido | 0.7500 | 0.0519 | 0.2100 | 0.2100 | 0.5281 | 0.0278 |
| N.º Compis | N.º Compis | 0.2500 | 0.1000 | 0.3000 | 0.3000 | 0.3000 | 0.0000 |
2.4 Conclusiones del Método AHP
Estudio de Inconsistencia
Un paso fundamental en AHP es verificar la consistencia. Como se observa en la “Tabla de Resultados Finales” (Tabla 1), el ratio de inconsistencia (Inconsistency) del objetivo principal (“Mejor Piso de Alquiler”) es de 0.0442. Todas las demás matrices de la jerarquía también presentan ratios muy por debajo del límite máximo permitido de 0.10 (ej. Económico con 0.0367, Tiempo Uni con 0.0991).
Por tanto, las valoraciones han sido coherentes y los resultados del método AHP son robustos y fiables.
Comentarios al Ranking
El ranking final obtenido mediante el paquete ahp es el siguiente:
- C_Barato (34.8%)
- A_Cercano (26.2%)
- D_Centrico (20.6%)
- B_Reformado (18.4%)
Este resultado es lógico:
- El
C_Baratogana de forma clara gracias a su dominio absoluto en el criterio de “Alquiler” (ver Tabla 2,C_Baratotiene un 0.6574 de prioridad local en Alquiler). Dado que “Económico” es el criterio principal con más peso (56.5%), esta ventaja es decisiva. - El
A_Cercanoobtiene el segundo puesto gracias a sus excelentes puntuaciones en “Tiempo Uni” (prioridad local de 0.6987) y “Transporte” (0.7039), ambos subcriterios importantes. - El
B_Reformadoqueda último, ya que sus fortalezas (Calidad, Ruido) están en criterios que hemos ponderado como menos importantes.
Este ranking es prácticamente idéntico al que se obtiene en la Sección 3 con las funciones R (34.1%), lo que valida ambos métodos.
3. Método AHP (con R)
En este apartado, se replica el análisis AHP utilizando las funciones R proporcionadas por la asignatura. Para ello, primero debemos cargar dichas funciones, que deben estar en la carpeta del proyecto.
# --- Cargar Funciones del Profesor ---
source("teoriadecision_funciones_multicriterio.R")
source("teoriadecision_funciones_multicriterio_utiles.R")
source("teoriadecision_funciones_multicriterio_diagram.R")Cargando paquete requerido: shape
# También cargamos las librerías para las tablas
library(knitr)
library(kableExtra)
# 1. Crear la matriz de Criterios Principales
# El vector de la diagonal superior es: (E-U), (E-C), (E-A), (U-C),
# (U-A), (C-A)
mat_c1 <- multicriterio.crea.matrizvaloraciones_mej(
vector_valoraciones_diagsup = c(3, 5, 7, 3, 5, 3),
numalternativas = 4,
v.nombres.alternativas = c("Económico", "Ubicación", "Calidad", "Ambiente")
)
# 2. Calcular los pesos locales
pesos_c1_R <-
multicriterio.metodoAHP.variante3.basico(mat_c1)$valoraciones.ahp
# 3. Calcular la Inconsistencia (Requisito de la evaluación)
incons_c1_R <- multicriterio.metodoAHP.coef.inconsistencia(mat_c1)
kbl(mat_c1, digits = 3, caption = "Matriz Criterios Principales (AHP-R)") %>%
kable_styling(bootstrap_options = "striped", full_width = F,
position = "center")| Económico | Ubicación | Calidad | Ambiente | |
|---|---|---|---|---|
| Económico | 1.000 | 3.000 | 5.000 | 7 |
| Ubicación | 0.333 | 1.000 | 3.000 | 5 |
| Calidad | 0.200 | 0.333 | 1.000 | 3 |
| Ambiente | 0.143 | 0.200 | 0.333 | 1 |
kbl(t(pesos_c1_R), digits = 4, caption =
"Pesos Locales Criterios Principales") %>%
kable_styling(bootstrap_options = "striped", full_width = T,
position = "center")| Económico | Ubicación | Calidad | Ambiente |
|---|---|---|---|
| 0.5579 | 0.2633 | 0.1219 | 0.0569 |
print(paste("Ratio de Inconsistencia (C1):",
round(incons_c1_R$RI.coef.inconsistencia, 4)))[1] "Ratio de Inconsistencia (C1): 0.0433"
3.2. Nivel 2: Subcriterios
Ahora, definimos las matrices de comparación para los subcriterios que dependen de cada criterio principal.
# 1. Matriz de Subcriterios de C1: Económico (3x3)
# [Alquiler (5) vs Gastos], [Alquiler (3) vs Transporte],
# [Gastos (1/3) vs Transporte]
mat_c1_sub <- multicriterio.crea.matrizvaloraciones_mej(
vector_valoraciones_diagsup = c(5, 3, 1/3),
numalternativas = 3,
v.nombres.alternativas = c("Alquiler", "Gastos", "Transporte")
)
pesos_c1_sub_R <-
multicriterio.metodoAHP.variante3.basico(mat_c1_sub)$valoraciones.ahp
incons_c1_sub_R <- multicriterio.metodoAHP.coef.inconsistencia(mat_c1_sub)
print(paste("Ratio de Inconsistencia (C1-Sub Económico):",
round(incons_c1_sub_R$RI.coef.inconsistencia, 4)))[1] "Ratio de Inconsistencia (C1-Sub Económico): 0.0332"
# 2. Matriz de Subcriterios de C2: Ubicación (3x3)
# [Tiempo Uni (3) vs Conexión], [Tiempo Uni (5) vs Servicios],
# [Conexión (3) vs Servicios]
mat_c2_sub <- multicriterio.crea.matrizvaloraciones_mej(
vector_valoraciones_diagsup = c(3, 5, 3),
numalternativas = 3,
v.nombres.alternativas = c("Tiempo Uni", "Conexión", "Servicios")
)
pesos_c2_sub_R <-
multicriterio.metodoAHP.variante3.basico(mat_c2_sub)$valoraciones.ahp
incons_c2_sub_R <- multicriterio.metodoAHP.coef.inconsistencia(mat_c2_sub)
print(paste("Ratio de Inconsistencia (C2-Sub Ubicación):",
round(incons_c2_sub_R$RI.coef.inconsistencia, 4)))[1] "Ratio de Inconsistencia (C2-Sub Ubicación): 0.0332"
# 3. Matriz de Subcriterios de C3: Calidad (2x2)
# [Estado (1) vs Tamaño Hab.]
mat_c3_sub <- multicriterio.crea.matrizvaloraciones_mej(
vector_valoraciones_diagsup = c(1),
numalternativas = 2,
v.nombres.alternativas = c("Estado", "Tamaño Hab.")
)
pesos_c3_sub_R <-
multicriterio.metodoAHP.variante3.basico(mat_c3_sub)$valoraciones.ahp
incons_c3_sub_R <- multicriterio.metodoAHP.coef.inconsistencia(mat_c3_sub)
print(paste("Ratio de Inconsistencia (C3-Sub Calidad):",
round(incons_c3_sub_R$RI.coef.inconsistencia, 4)))[1] "Ratio de Inconsistencia (C3-Sub Calidad): NaN"
# 4. Matriz de Subcriterios de C4: Ambiente (2x2)
# [Ruido (3) vs N.º Compis]
mat_c4_sub <- multicriterio.crea.matrizvaloraciones_mej(
vector_valoraciones_diagsup = c(3),
numalternativas = 2,
v.nombres.alternativas = c("Ruido", "N.º Compis")
)
pesos_c4_sub_R <-
multicriterio.metodoAHP.variante3.basico(mat_c4_sub)$valoraciones.ahp
incons_c4_sub_R <- multicriterio.metodoAHP.coef.inconsistencia(mat_c4_sub)
print(paste("Ratio de Inconsistencia (C4-Sub Ambiente):",
round(incons_c4_sub_R$RI.coef.inconsistencia, 4)))[1] "Ratio de Inconsistencia (C4-Sub Ambiente): NaN"
# Mostramos las tablas de pesos de los subcriterios
kbl(t(pesos_c1_sub_R), digits = 4, caption =
"Pesos Subcriterios de Económico (AHP-R)") %>%
kable_styling(bootstrap_options = "striped", full_width = T,
position = "center")| Alquiler | Gastos | Transporte |
|---|---|---|
| 0.6333 | 0.1062 | 0.2605 |
kbl(t(pesos_c2_sub_R), digits = 4, caption =
"Pesos Subcriterios de Ubicación (AHP-R)") %>%
kable_styling(bootstrap_options = "striped", full_width = T,
position = "center")| Tiempo Uni | Conexión | Servicios |
|---|---|---|
| 0.6333 | 0.2605 | 0.1062 |
kbl(t(pesos_c3_sub_R), digits = 4, caption =
"Pesos Subcriterios de Calidad (AHP-R)") %>%
kable_styling(bootstrap_options = "striped", full_width = T,
position = "center")| Estado | Tamaño Hab. |
|---|---|
| 0.5 | 0.5 |
kbl(t(pesos_c4_sub_R), digits = 4, caption =
"Pesos Subcriterios de Ambiente (AHP-R)") %>%
kable_styling(bootstrap_options = "striped", full_width = T,
position = "center")| Ruido | N.º Compis |
|---|---|
| 0.75 | 0.25 |
3.3. Nivel 3: Alternativas
Finalmente, se crean las 10 matrices de comparación para las 4 alternativas, una por cada subcriterio. Para cada matriz, se calculan los pesos locales y el ratio de inconsistencia.
# Definimos los nombres de las alternativas
v_nombres_alt <- c("A_Cercano", "B_Reformado", "C_Barato", "D_Centrico")
num_alt <- 4
lista_pesos_locales <- list()
lista_inconsistencia <- list()
# 1. C1.1: Alquiler (min)
# Lógica: C(250) > D(350) > B(380) > A(450)
# Vectores (A-B, A-C, A-D, B-C, B-D, C-D)
mat_alt_1_alquiler <- multicriterio.crea.matrizvaloraciones_mej(
c(1/3, 1/9, 1/5, 1/7, 1/3, 5), num_alt, v_nombres_alt)
pesos_alt_1_alquiler_R <-
multicriterio.metodoAHP.variante3.basico(mat_alt_1_alquiler)$valoraciones.ahp
lista_pesos_locales[["Alquiler"]] <- pesos_alt_1_alquiler_R
lista_inconsistencia[["Alquiler"]] <-
multicriterio.metodoAHP.coef.inconsistencia(mat_alt_1_alquiler)$RI.coef.inconsistencia
# 2. C1.2: Gastos (min)
# Lógica: A(50) = B(50) > D(55) > C(60)
mat_alt_2_gastos <- multicriterio.crea.matrizvaloraciones_mej(
c(1, 1/3, 1/5, 1/3, 1/5, 1/3), num_alt, v_nombres_alt)
pesos_alt_2_gastos_R <-
multicriterio.metodoAHP.variante3.basico(mat_alt_2_gastos)$valoraciones.ahp
lista_pesos_locales[["Gastos"]] <- pesos_alt_2_gastos_R
lista_inconsistencia[["Gastos"]] <-
multicriterio.metodoAHP.coef.inconsistencia(mat_alt_2_gastos)$RI.coef.inconsistencia
# 3. C1.3: Transporte (min)
# Lógica: A(0) > B(30) = D(30) > C(45)
mat_alt_3_transporte <- multicriterio.crea.matrizvaloraciones_mej(
c(7, 9, 7, 3, 1, 1/3), num_alt, v_nombres_alt)
pesos_alt_3_transporte_R <-
multicriterio.metodoAHP.variante3.basico(mat_alt_3_transporte)$valoraciones.ahp
lista_pesos_locales[["Transporte"]] <- pesos_alt_3_transporte_R
lista_inconsistencia[["Transporte"]] <-
multicriterio.metodoAHP.coef.inconsistencia(mat_alt_3_transporte)$RI.coef.inconsistencia
# 4. C2.1: Tiempo Uni (min)
# Lógica: A(5) > B(25) > D(30) > C(45)
mat_alt_4_tiempo <- multicriterio.crea.matrizvaloraciones_mej(
c(7, 9, 8, 5, 3, 1/3), num_alt, v_nombres_alt)
pesos_alt_4_tiempo_R <-
multicriterio.metodoAHP.variante3.basico(mat_alt_4_tiempo)$valoraciones.ahp
lista_pesos_locales[["Tiempo Uni"]] <- pesos_alt_4_tiempo_R
lista_inconsistencia[["Tiempo Uni"]] <-
multicriterio.metodoAHP.coef.inconsistencia(mat_alt_4_tiempo)$RI.coef.inconsistencia
# 5. C2.2: Conexión (max)
# Lógica: B(5) = D(5) > A(3) > C(2)
mat_alt_5_conexion <- multicriterio.crea.matrizvaloraciones_mej(
c(1/5, 1/7, 1/5, 1, 3, 5), num_alt, v_nombres_alt)
pesos_alt_5_conexion_R <-
multicriterio.metodoAHP.variante3.basico(mat_alt_5_conexion)$valoraciones.ahp
lista_pesos_locales[["Conexión"]] <- pesos_alt_5_conexion_R
lista_inconsistencia[["Conexión"]] <-
multicriterio.metodoAHP.coef.inconsistencia(mat_alt_5_conexion)$RI.coef.inconsistencia
# 6. C2.3: Servicios (max)
# Lógica: D(5) > B(4) > A(3) > C(2)
mat_alt_6_servicios <- multicriterio.crea.matrizvaloraciones_mej(
c(1/3, 3, 1/5, 5, 1/3, 1/7), num_alt, v_nombres_alt)
pesos_alt_6_servicios_R <-
multicriterio.metodoAHP.variante3.basico(mat_alt_6_servicios)$valoraciones.ahp
lista_pesos_locales[["Servicios"]] <- pesos_alt_6_servicios_R
lista_inconsistencia[["Servicios"]] <-
multicriterio.metodoAHP.coef.inconsistencia(mat_alt_6_servicios)$RI.coef.inconsistencia
# 7. C3.1: Estado (max)
# Lógica: B(5) > D(3) > A(2) = C(2)
mat_alt_7_estado <- multicriterio.crea.matrizvaloraciones_mej(
c(1/7, 1, 1/3, 7, 5, 1/3), num_alt, v_nombres_alt)
pesos_alt_7_estado_R <-
multicriterio.metodoAHP.variante3.basico(mat_alt_7_estado)$valoraciones.ahp
lista_pesos_locales[["Estado"]] <- pesos_alt_7_estado_R
lista_inconsistencia[["Estado"]] <-
multicriterio.metodoAHP.coef.inconsistencia(mat_alt_7_estado)$RI.coef.inconsistencia
# 8. C3.2: Tamaño Hab. (max)
# Lógica: C(15) > B(12) > A(10) = D(10)
mat_alt_8_tamano <- multicriterio.crea.matrizvaloraciones_mej(
c(1/3, 1/5, 1, 1/3, 3, 5), num_alt, v_nombres_alt)
pesos_alt_8_tamano_R <-
multicriterio.metodoAHP.variante3.basico(mat_alt_8_tamano)$valoraciones.ahp
lista_pesos_locales[["Tamaño Hab."]] <- pesos_alt_8_tamano_R
lista_inconsistencia[["Tamaño Hab."]] <-
multicriterio.metodoAHP.coef.inconsistencia(mat_alt_8_tamano)$RI.coef.inconsistencia
# 9. C4.1: Ruido (min)
# Lógica: B(2) = C(2) > A(4) > D(5)
mat_alt_9_ruido <- multicriterio.crea.matrizvaloraciones_mej(
c(1/5, 1/5, 1/7, 1, 1/3, 1/3), num_alt, v_nombres_alt)
pesos_alt_9_ruido_R <-
multicriterio.metodoAHP.variante3.basico(mat_alt_9_ruido)$valoraciones.ahp
lista_pesos_locales[["Ruido"]] <- pesos_alt_9_ruido_R
lista_inconsistencia[["Ruido"]] <-
multicriterio.metodoAHP.coef.inconsistencia(mat_alt_9_ruido)$RI.coef.inconsistencia
# 10. C4.2: N.º Compis (min)
# Lógica: B(2) = D(2) > A(3) = C(3)
mat_alt_10_compis <- multicriterio.crea.matrizvaloraciones_mej(
c(1/3, 1/3, 1/3, 1, 1, 1), num_alt, v_nombres_alt)
pesos_alt_10_compis_R <-
multicriterio.metodoAHP.variante3.basico(mat_alt_10_compis)$valoraciones.ahp
lista_pesos_locales[["N.º Compis"]] <- pesos_alt_10_compis_R
lista_inconsistencia[["N.º Compis"]] <-
multicriterio.metodoAHP.coef.inconsistencia(mat_alt_10_compis)$RI.coef.inconsistencia
# Imprimir el estudio de inconsistencia
inconsistencia_df <- data.frame(Ratio_Inconsistencia = unlist(lista_inconsistencia))
kbl(inconsistencia_df, digits = 4,
caption = "Inconsistencia de las 10 Matrices de Alternativas") %>%
kable_styling(bootstrap_options = "striped", full_width = F,
position = "center")| Ratio_Inconsistencia | |
|---|---|
| Alquiler | 0.0632 |
| Gastos | 0.0161 |
| Transporte | 0.0337 |
| Tiempo Uni | 0.0970 |
| Conexión | 0.0760 |
| Servicios | 0.0433 |
| Estado | 0.0272 |
| Tamaño Hab. | 0.0161 |
| Ruido | 0.0272 |
| N.º Compis | 0.0000 |
3.4. Cálculo del Ranking Global (AHP-R)
Finalmente, se calcula el ranking global. Para ello, primero se calcula el peso global de cada uno de los 10 subcriterios (hojas del árbol) multiplicando el peso de su criterio principal por su peso local.
# 1. Calcular el vector de pesos globales de los 10 subcriterios
# (Peso Criterio * Peso Local Subcriterio)
vec_pesos_globales_sub_R <- c(
pesos_c1_R[1] * pesos_c1_sub_R, # Pesos de Económico * Sub-pesos de Económico
pesos_c1_R[2] * pesos_c2_sub_R, # Pesos de Ubicación * Sub-pesos de Ubicación
pesos_c1_R[3] * pesos_c3_sub_R, # Pesos de Calidad * Sub-pesos de Calidad
pesos_c1_R[4] * pesos_c4_sub_R # Pesos de Ambiente * Sub-pesos de Ambiente
)
# 2. Crear la matriz de pesos de alternativas
# (10 Subcriterios x 4 Alternativas)
# Usamos 'do.call(rbind, ...)' para unir los 10 vectores de la lista
mat_alt_final_R <- do.call(rbind, lista_pesos_locales)
# 3. Calcular el ranking final (Producto matricial)
# (1x10) %*% (10x4) = (1x4)
# Esto es: (Pesos Globales Subcriterios) %*% (Pesos Locales Alternativas)
ranking_final_R <- vec_pesos_globales_sub_R %*% mat_alt_final_R
# 4. Formatear y mostrar la tabla de resultados
ranking_df_R <- as.data.frame(t(ranking_final_R))
colnames(ranking_df_R) <- "Ponderacion_Global_AHP_R"
ranking_df_R <- ranking_df_R[order(ranking_df_R$Ponderacion_Global_AHP_R,
decreasing = TRUE), , drop = FALSE]
kbl(ranking_df_R, digits = 4,
caption = "Ranking Final (AHP con Funciones R)") %>%
kable_styling(bootstrap_options = "striped", full_width = F,
position = "center")| Ponderacion_Global_AHP_R | |
|---|---|
| C_Barato | 0.3411 |
| A_Cercano | 0.2574 |
| D_Centrico | 0.2109 |
| B_Reformado | 0.1906 |
3.5. Conclusiones del Método AHP (con R)
Estudio de Inconsistencia: Como se vio en los chunks anteriores, se ha calculado el Ratio de Inconsistencia (RI) para cada una de las 14 matrices de comparación. Todos los valores (ej. 0.0433 para la matriz de criterios principales) están por debajo del límite del 10%, validando la coherencia de los juicios.
Ranking Final: El ranking obtenido (ver Tabla “Ranking Final (AHP con Funciones R)”) da como claro ganador al
C_Barato(34.11%). Esto se debe a que el criterio “Económico” fue ponderado como el más importante (55.8% del peso total) y el pisoC_Baratodomina en “Alquiler”. El método AHP permite que esta ventaja compense su mala “Ubicación”. En segundo lugar, quedaA_Cercano(25.74%), que gana en los subcriterios de “Tiempo Uni” y “Transporte”.
Este resultado confirma el ranking obtenido en la Sección 2 con el paquete ahp (34.8%), demostrando la coherencia de los cálculos.
4. Método ELECTRE I
El método ELECTRE es un enfoque basado en la comparación por pares de alternativas, utilizando los conceptos de concordancia y discordancia para establecer relaciones de dominancia.
A diferencia de AHP, ELECTRE I es un método no compensatorio (una muy mala nota no se puede compensar con una buena) y puede dar como resultado un “núcleo” de alternativas incomparables, en lugar de un ranking único.
4.1 Carga de Funciones y Preparación de Datos
Para mantener la consistencia del análisis, se utilizan los resultados del método AHP (Sección 2) como datos de entrada. Las funciones del profesor ya fueron cargadas en la sección anterior.
# Cargamos la librería para los grafos de dominancia
library(qgraph)4.2. Creación de la Matriz de Decisión para ELECTRE
A partir de los datos de AHP, se construye la matriz de decisión que requiere ELECTRE. Usaremos la tabla de “Prioridades Locales” (la Tabla 2 de la Sección 2), que nos dice cómo puntúa cada piso en cada subcriterio.
# 1. Definir los nombres de los 10 subcriterios (hojas del árbol)
nombres_subcriterios <- c("Alquiler", "Gastos", "Transporte",
"Tiempo Uni", "Conexión", "Servicios",
"Estado", "Tamaño Hab.",
"Ruido", "N.º Compis")
# 2. Definir los nombres de las 4 alternativas
nombres_alternativas <- c("A_Cercano", "B_Reformado", "C_Barato", "D_Centrico")
# 3. Crear la matriz base desde la "Tabla 2" (results_priority)
# Esta es la matriz (Subcriterios x Alternativas)
matriz_base <- results_priority[nombres_subcriterios, nombres_alternativas]
# 4. Transponer la matriz para tener (Alternativas x Criterios)
matriz_electre <- t(matriz_base)
# 5. Mostrar la matriz de decisión que usaremos
kbl(matriz_electre, digits = 3, caption = "Matriz de Decisión para ELECTRE (Alternativas x Criterios)") %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "center")| Alquiler | Gastos | Transporte | Tiempo Uni | Conexión | Servicios | Estado | Tamaño Hab. | Ruido | N.º Compis | |
|---|---|---|---|---|---|---|---|---|---|---|
| A_Cercano | 0.046 | 0.095 | 0.704 | 0.699 | 0.051 | 0.118 | 0.076 | 0.095 | 0.052 | 0.1 |
| B_Reformado | 0.094 | 0.095 | 0.122 | 0.174 | 0.355 | 0.262 | 0.657 | 0.249 | 0.210 | 0.3 |
| C_Barato | 0.657 | 0.249 | 0.052 | 0.043 | 0.449 | 0.055 | 0.076 | 0.560 | 0.210 | 0.3 |
| D_Centrico | 0.203 | 0.560 | 0.122 | 0.084 | 0.145 | 0.565 | 0.191 | 0.095 | 0.528 | 0.3 |
4.3 Definición de Pesos y Parámetros
# 1. Preparar Pesos (W)
# Extraemos los pesos GLOBALES de los subcriterios de la "Tabla 1" (results_table)
pesos_globales_ahp <- results_table[nombres_subcriterios, "Weight"]
# Normalizar los pesos para que sumen 1 (requisito de la función ELECTRE)
pesos_electre_norm <- pesos_globales_ahp / sum(pesos_globales_ahp)
kbl(t(pesos_electre_norm), digits = 3, caption = "Vector de Pesos (W) para ELECTRE") %>%
kable_styling(bootstrap_options = "striped", full_width = T, position = "center")| 0.36 | 0.059 | 0.146 | 0.167 | 0.068 | 0.027 | 0.059 | 0.059 | 0.041 | 0.014 |
# 2. Preparar Parámetros de Concordancia y Veto (Discordancia)
# Nivel de Concordancia (alpha):
# Aceptamos que A domina a B si la suma de pesos de los criterios donde A>B es >= 70%
alpha_concordancia <- 0.7
# Umbrales de Discordancia (d_i) o "Vetos"
# La matriz de decisión tiene valores de 0 a 1 (son pesos).
# Establecemos un VETO si un piso es MUCHO peor que otro en un criterio clave.
# Los criterios más importantes son "Alquiler" y "Tiempo Uni".
# Si la diferencia en la puntuación local (que es un peso) es mayor a 0.30 (30%), vetamos la dominancia.
umbrales_discordancia <- c(
0.30, # C1.1 Alquiler (Veto si la diferencia es > 30%)
Inf, # C1.2 Gastos (Sin veto)
Inf, # C1.3 Transporte (Sin veto)
0.30, # C2.1 Tiempo Uni (Veto si la diferencia es > 30%)
Inf, # C2.2 Conexión (Sin veto)
Inf, # C2.3 Servicios (Sin veto)
Inf, # C3.1 Estado (Sin veto)
Inf, # C3.2 Tamaño Hab. (Sin veto)
Inf, # C4.1 Ruido (Sin veto)
Inf # C4.2 N.º Compis (Sin veto)
)4.4 Ejecución y Análisis Iterativo
Realizamos un análisis iterativo para encontrar el núcleo del grafo de superación, tal como se pide en la evaluación.
- Iteración 1: Todas las alternativas
Primero, ejecutamos el método con las 4 alternativas.
#Ejecutar ELECTRE I (Iteración 1)
# 1. Ejecutar ELECTRE I con la función de la asignatura
salida_electre1 <- multicriterio.metodoELECTRE_I(
tabdecs.X = matriz_electre,
pesos.criterios = pesos_electre_norm,
nivel.concordancia.minimo.alpha = alpha_concordancia,
no.se.compensan = umbrales_discordancia
)
# 2. Mostrar el núcleo (las mejores alternativas)
print("--- ELECTRE Iteración 1: Núcleo Aproximado ---")[1] "--- ELECTRE Iteración 1: Núcleo Aproximado ---"
print(salida_electre1$nucleo_aprox) A_Cercano B_Reformado C_Barato D_Centrico
1 2 3 4
# 3. Mostrar el grafo de dominancia
qgraph::qgraph(salida_electre1$relacion.dominante,
labels = rownames(matriz_electre),
edge.labels = FALSE,
posCol = "blue",
label.cex = 1.2,
label.color = "black",
vsize = 10,
title = "ELECTRE I: Grafo de Dominancia (Iteración 1)")- Iteración 2: Filtrado del Núcleo
El núcleo de la Iteración 1 nos devolverá un conjunto de alternativas (el/los ganador/es). Si hay más de una, repetimos el análisis solo con ellas para intentar desempatar.
# Ejecutar ELECTRE I (Iteración 2)
# 1. Identificamos las alternativas del núcleo anterior
alternativas_nucleo1 <- salida_electre1$nucleo_aprox
# Comprobamos si hay algo que filtrar
if (length(alternativas_nucleo1) > 0 && length(alternativas_nucleo1) < nrow(matriz_electre)) {
alternativas_nucleo1_nombres <- names(alternativas_nucleo1)
print("--- Ejecutando ELECTRE I: Iteración 2 (solo núcleo) ---")
print("Alternativas en esta iteración:")
print(alternativas_nucleo1_nombres)
# 2. Ejecutamos ELECTRE I de nuevo, filtrando por el núcleo
salida_electre2 <- multicriterio.metodoELECTRE_I(
tabdecs.X = matriz_electre,
pesos.criterios = pesos_electre_norm,
nivel.concordancia.minimo.alpha = alpha_concordancia,
no.se.compensan = umbrales_discordancia,
que.alternativas = alternativas_nucleo1_nombres # ¡Filtro clave!
)
# 3. Imprimir el núcleo final
print("--- ELECTRE Iteración 2: Núcleo Final ---")
print(salida_electre2$nucleo_aprox)
# 4. Mostrar el grafo de dominancia final
print("--- ELECTRE Iteración 2: Grafo de Dominancia Final ---")
qgraph::qgraph(salida_electre2$relacion.dominante,
labels = alternativas_nucleo1_nombres,
edge.labels = FALSE,
posCol = "blue",
label.cex = 1.2,
label.color = "black",
vsize = 10,
title = "ELECTRE I: Grafo de Dominancia (Iteración 2)")
} else {
print("--- ELECTRE Iteración 2: No necesaria ---")
print("El núcleo de la Iteración 1 ya es el resultado final (o está vacío o incluye todas las alternativas).")
}[1] "--- ELECTRE Iteración 2: No necesaria ---"
[1] "El núcleo de la Iteración 1 ya es el resultado final (o está vacío o incluye todas las alternativas)."
4.5 Conclusiones del Método ELECTRE I
El método ELECTRE I se ha ejecutado siguiendo el paso a paso requerido.
- Iteración 1: Al ejecutar el método con las 4 alternativas, el grafo de superación (ver Grafo “ELECTRE I: Grafo de Dominancia (Iteración 1)”) no mostró ninguna flecha. Esto significa que, bajo los parámetros establecidos (\(\alpha=0.7\) y los vetos en “Alquiler” y “Tiempo Uni”), ninguna alternativa domina a otra.
- Resultado: Como ninguna alternativa es dominada, el núcleo aproximado resultante incluye a todas las alternativas:
[A_Cercano, B_Reformado, C_Barato, D_Centrico]. - Iteración 2: Al ser el núcleo igual al conjunto original, el análisis concluye en la primera iteración.
Conclusión: ELECTRE I, a diferencia de AHP, no nos da un ganador. Concluye que las cuatro opciones son incomparables entre sí. Esto se debe a los fuertes conflictos entre criterios clave (ej. “Alquiler” vs. “Tiempo Uni”) que el método no puede compensar.
5. Método PROMETHEE II
El método PROMETHEE II es un enfoque de decisión multicriterio que utiliza funciones de preferencia para comparar alternativas y generar un ranking completo basado en flujos netos (Phi).
5.1. Definición de Parámetros y Funciones de Preferencia
Este es el paso clave de PROMETHEE. Reutilizamos la matriz de decisión y los pesos de ELECTRE, pero debemos definir las funciones de preferencia generalizadas y los parámetros (p, q) para cada uno de los 10 subcriterios.
# Definir Parámetros de PROMETHEE
# 1. Matriz de Decisión: Reutilizamos la de ELECTRE
# (matriz_electre)
# 2. Pesos: Reutilizamos los de ELECTRE (normalizados de AHP)
pesos_promethee <- pesos_electre_norm
# 3. Vector min/max:
# TODOS nuestros criterios son "max" porque la matriz de decisión
# (matriz_electre) contiene los "pesos locales" de AHP (donde más es mejor).
vec_fminmax <- rep("max", ncol(matriz_electre))
# 4. Tabla de Funciones de Preferencia (tab.fpref)
# Aquí definimos el "tipo" de criterio (1-6) y sus umbrales.
# Usaremos:
# Tipo 1 (Usual): Para criterios menos importantes (diferencia 0 o 1)
# Tipo 3 (V-shape): Para criterios importantes (preferencia lineal)
# Tipo 5 (Linear c/ indif): Para criterios donde pequeñas diferencias no importan.
# Los valores (p, q) son sobre los pesos (0 a 1).
# q = umbral de indiferencia (ej. 0.05 = 5%)
# p = umbral de preferencia (ej. 0.20 = 20%)
tab_fpref_promethee <- matrix(
c(
# Criterio, q (indiferencia), p (preferencia), s (gaussiano)
3, 0.00, 0.25, 0, # C1.1 Alquiler: V-shape (p=25%)
1, 0.00, 0.00, 0, # C1.2 Gastos: Usual
3, 0.00, 0.20, 0, # C1.3 Transporte: V-shape (p=20%)
3, 0.00, 0.25, 0, # C2.1 Tiempo Uni: V-shape (p=25%)
1, 0.00, 0.00, 0, # C2.2 Conexión: Usual
1, 0.00, 0.00, 0, # C2.3 Servicios: Usual
5, 0.05, 0.20, 0, # C3.1 Estado: Linear c/ indif (q=5%, p=20%)
1, 0.00, 0.00, 0, # C3.2 Tamaño Hab.: Usual
1, 0.00, 0.00, 0, # C4.1 Ruido: Usual
1, 0.00, 0.00, 0 # C4.2 N.º Compis: Usual
),
ncol = 4,
byrow = TRUE
)5.2. Ejecución y Resultados de PROMETHEE II
Ahora, ejecutamos el método. Este generará un ranking completo de las 4 alternativas, ordenándolas por su flujo neto (Phi).
# Ejecutar PROMETHEE
# (Asegúrate de tener la función multicriterio.metodo.promethee_windows)
salida_promethee <- multicriterio.metodo.promethee_windows(
matdecision = matriz_electre,
tab.fpref = tab_fpref_promethee,
pesos.criterios = pesos_promethee,
fminmax = vec_fminmax
)
# La función del profesor devuelve una lista de tablas formateadas para kableExtra
tablas_promethee <- multicriterio.metodo.promethee_windows_kableExtra(salida_promethee)- Tabla de Escenario (Parámetros)
A continuación, se muestra la tabla de escenario que resume los parámetros, pesos y las funciones de preferencia utilizadas.
# Mostrar Tabla de Escenario
tablas_promethee$tabEscenario| Criterio1 | Criterio2 | Criterio3 | Criterio4 | Criterio5 | Criterio6 | Criterio7 | Criterio8 | Criterio9 | Criterio10 | |
|---|---|---|---|---|---|---|---|---|---|---|
| Preferencias | ||||||||||
| Min/Max | max | max | max | max | max | max | max | max | max | max |
| Pesos | 0.35990261517515 | 0.0591730783418713 | 0.145933360282026 | 0.167018384836357 | 0.067722636903276 | 0.0274601838212399 | 0.0587521250206993 | 0.0587521250206993 | 0.0414641179490107 | 0.0138213726496702 |
| Funciones Preferencias | V-shape (3) | Usual (1) | V-shape (3) | V-shape (3) | Usual (1) | Usual (1) | Linear (5) | Usual (1) | Usual (1) | Usual (1) |
| Q: Indiferencia | 0 | 0 | 0 | 0 | 0 | 0 | 0.05 | 0 | 0 | 0 |
| P: Preferencia | 0.25 | 0 | 0.2 | 0.25 | 0 | 0 | 0.2 | 0 | 0 | 0 |
| S: Gausiano | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Estadísticas | ||||||||||
| Minimo | 0.05 | 0.1 | 0.05 | 0.04 | 0.05 | 0.06 | 0.08 | 0.1 | 0.05 | 0.1 |
| Maximo | 0.66 | 0.56 | 0.7 | 0.7 | 0.45 | 0.57 | 0.66 | 0.56 | 0.53 | 0.3 |
| Media | 0.25 | 0.25 | 0.25 | 0.25 | 0.25 | 0.25 | 0.25 | 0.25 | 0.25 | 0.25 |
| Desviacion Tipica | 0.24 | 0.19 | 0.26 | 0.26 | 0.16 | 0.2 | 0.24 | 0.19 | 0.17 | 0.09 |
| Evaluaciones | ||||||||||
| A_Cercano | 0.0457252520455664 | 0.0954636795985965 | 0.703923192113878 | 0.698725302346839 | 0.0512039650335782 | 0.117504250041399 | 0.0759811736222761 | 0.0954636795985966 | 0.0518782606731856 | 0.1 |
| B_Reformado | 0.0941925573482837 | 0.0954636795985965 | 0.122208037501528 | 0.174031692855278 | 0.3553736837665 | 0.262201205560873 | 0.656957500264322 | 0.24948657690151 | 0.210001392090931 | 0.3 |
| C_Barato | 0.65738637891435 | 0.249486576901509 | 0.0516607328830671 | 0.0430716911110433 | 0.448601057696833 | 0.0552854905986809 | 0.0759811736222761 | 0.559586063901297 | 0.210001392090931 | 0.3 |
| D_Centrico | 0.2026958116918 | 0.559586063901297 | 0.122208037501528 | 0.0841713136868396 | 0.144821293503089 | 0.565009053799047 | 0.191080152491126 | 0.0954636795985965 | 0.528118955144953 | 0.3 |
- Tabla de Ranking (Resultados)
La siguiente tabla muestra el ranking final de las alternativas. El orden se basa en el flujo neto (Phi).
# Mostrar Tabla de Ranking
tablas_promethee$tabAcciones| Rango | Phi | Phi.mas | Phi.menos | |
|---|---|---|---|---|
| C_Barato | 1 | 0.2598 | 0.5443 | 0.2845 |
| D_Centrico | 2 | -0.0464 | 0.3260 | 0.3724 |
| B_Reformado | 3 | -0.0688 | 0.3122 | 0.3809 |
| A_Cercano | 4 | -0.1446 | 0.3417 | 0.4863 |
5.3. Conclusiones del Método PROMETHEE II
El método PROMETHEE II, a diferencia de ELECTRE I, sí nos proporciona un ranking completo de las alternativas, basado en el Flujo Neto (Phi). Este flujo se calcula como la diferencia entre el flujo positivo (Phi.mas, o las fortalezas) y el flujo negativo (Phi.menos, o las debilidades) de cada alternativa.
El ranking final obtenido es:
- C_Barato (Phi = 0.2598)
- D_Centrico (Phi = -0.0464)
- B_Reformado (Phi = -0.0688)
- A_Cercano (Phi = -0.1446)
Análisis de la tabla:
- El Ganador: El
C_Baratorepite como ganador, y es la única alternativa con un flujo neto positivo. La “Tabla de Ranking” (tabAcciones) muestra que gana por un doble motivo: tiene elPhi.mas(fortalezas) más alto (0.5443) y elPhi.menos(debilidades) más bajo (0.2845). - Diferencia clave con AHP: El cambio más drástico está en el
A_Cercano. En AHP (un método compensatorio) quedó en 2º lugar, pero en PROMETHEE (un método de flujos netos) cae al último puesto. - Justificación: Esto se debe a su
Phi.menosde 0.4863, el más alto de todos. Sus grandes debilidades (principalmente ser el más caro en “Alquiler”) no se compensan, y provocan que sea superado frecuentemente por las otras alternativas, hundiéndole el flujo neto.
Conclusión: PROMETHEE II, usando las funciones de preferencia definidas, ratifica al C_Barato como la mejor opción por ser la más equilibrada y con menos debilidades.
6. Conclusiones Finales (Comparativa de Métodos)
En este trabajo se han aplicado tres métodos de decisión multicriterio (AHP, ELECTRE I y PROMETHEE II) para resolver el problema de la “Selección del mejor piso de alquiler para un estudiante”.
A continuación, se presenta una tabla comparativa con los rankings obtenidos por cada método:
| Rango | Método AHP (Secc. 2 y 3) | Método ELECTRE I (Secc. 4) | Método PROMETHEE II (Secc. 5) |
|---|---|---|---|
| 1º | C_Barato (34.8%) | Núcleo Incomparable | C_Barato (Phi: 0.260) |
| 2º | A_Cercano (26.2%) | (Ver Conclusión 4.5) | D_Centrico (Phi: -0.046) |
| 3º | D_Centrico (20.6%) | (Ver Conclusión 4.5) | B_Reformado (Phi: -0.069) |
| 4º | B_Reformado (18.4%) | (Ver Conclusión 4.5) | A_Cercano (Phi: -0.145) |
(Nota: La celda “Núcleo Incomparable” solo se expandirá si se renderiza a PDF; en HTML se verá en la primera fila).
Justificación de las Diferencias entre Métodos
Tal como solicita la evaluación, el análisis de los tres métodos revela diferencias significativas que se explican por la lógica interna de cada uno:
- El Ganador (AHP vs PROMETHEE):
- Ambos métodos, AHP (agregación total) y PROMETHEE II (flujos netos), coinciden en que el ganador es el
C_Barato. Esto da una gran robustez a la decisión, ya que dos lógicas distintas llegan a la misma conclusión. ElC_Baratogana porque su dominio en el criterio más importante (“Económico”) es abrumador.
- Ambos métodos, AHP (agregación total) y PROMETHEE II (flujos netos), coinciden en que el ganador es el
- El Caso de
A_Cercano(AHP vs PROMETHEE):- La mayor diferencia radica en el
A_Cercano. En AHP (método compensatorio) queda 2º, porque su excelente “Tiempo Uni” compensa su pésimo “Alquiler”. - En PROMETHEE II (método no compensatorio basado en flujos), queda 4º (último). Sus debilidades (alto
Phi.menos) son tan grandes que no se compensan, y lo hunden en el ranking.
- La mayor diferencia radica en el
- El Caso de ELECTRE I (Incomparabilidad):
- AHP y PROMETHEE fuerzan un ranking completo.
- ELECTRE I (método de superación con vetos) es el único que respeta la incomparabilidad. Concluye que las 4 alternativas están en el núcleo (son incomparables). Esto se debe a los fuertes conflictos entre criterios (el “Alquiler” del
C_Baratovs. el “Tiempo Uni” delA_Cercano) y los vetos que establecimos, que impiden que un piso domine a otro.
Conclusión Final
No existe un “mejor método”, sino que cada uno aporta una visión diferente: * Si el decisor es compensatorio (un gran beneficio suple un gran coste), AHP le recomienda el C_Barato y pone segundo al A_Cercano. * Si el decisor es no compensatorio y busca el mejor balance fortalezas/debilidades, PROMETHEE II le recomienda el C_Barato y castiga duramente al A_Cercano por sus debilidades. * Si el decisor no acepta vetos (ej. “no quiero un piso que sea mucho peor que otro en ‘Tiempo Uni’”), ELECTRE I le dice que no hay una solución única y que los 4 pisos son incomparables.